home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 2: Applications / Linux Cubed Series 2 - Applications.iso / editors / emacs / xemacs / xemacs-1.004 / xemacs-1 / xemacs-19.13 / src / lstream.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-08-04  |  28.2 KB  |  1,064 lines

  1. /* Generic stream implementation.
  2.    Copyright (C) 1995 Amdahl Corporation.
  3.  
  4. This file is part of XEmacs.
  5.  
  6. XEmacs is free software; you can redistribute it and/or modify it
  7. under the terms of the GNU General Public License as published by the
  8. Free Software Foundation; either version 2, or (at your option) any
  9. later version.
  10.  
  11. XEmacs is distributed in the hope that it will be useful, but WITHOUT
  12. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13. FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14. for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with XEmacs; see the file COPYING.  If not, write to the Free
  18. Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20. /* Synched up with: Not in FSF. */
  21.  
  22. /* Written by Ben Wing. */
  23.  
  24. #include <config.h>
  25. #include "lisp.h"
  26.  
  27. #include "buffer.h"
  28. #include "lstream.h"
  29.  
  30. /* This function provides a generic buffering stream implementation.
  31.    Conceptually, you send data to the stream or read data from the
  32.    stream, not caring what's on the other end of the stream.  The
  33.    other end could be another stream, a file descriptor, a stdio
  34.    stream, a fixed block of memory, a reallocating block of memory,
  35.    etc.  The main purpose of the stream is to provide a standard
  36.    interface and to do buffering.  Macros are defined to read
  37.    or write characters, so the calling functions do not have to
  38.    worry about blocking data together in order to achieve efficiency.
  39.    */
  40.  
  41. /* Note that this object is called "stream" in Lisp but "lstream"
  42.    in C.  The reason for this is that "stream" is too generic a name
  43.    for C; too much likelihood of conflict/confusion with C++, etc. */
  44.  
  45. /* Functions are as follows:
  46.  
  47. Lstream *Lstream_new (Lstream_implementation *imp)
  48.     Allocate and return a new Lstream.  This function is not
  49.     really meant to be called directly; rather, each stream type
  50.     should provide its own stream creation function, which
  51.     creates the stream and does any other necessary creation
  52.     stuff (e.g. opening a file).
  53.  
  54. void Lstream_set_buffering (Lstream *lstr, Lstream_buffering buffering,
  55.                 int buffering_size)
  56.     Change the buffering of a stream.  See lstream.h.  By default
  57.     the buffering is STREAM_BLOCK_BUFFERED.
  58.  
  59. int Lstream_flush (Lstream *lstr)
  60.     Flush out any pending unwritten data in the stream.  Clear
  61.     any buffered input data.  Returns 0 on success, -1 on error.
  62.  
  63. int Lstream_putc (Lstream *stream, int c)
  64.     Write out one byte to the stream.  This is a macro and so
  65.     it is very efficient.  The C argument is only evaluated once
  66.     but the STREAM argument is evaluated more than once.  Returns
  67.     0 on success, -1 on error.
  68.     
  69. int Lstream_getc (Lstream *stream)
  70.     Read one byte from the stream.  This is a macro and so it
  71.     is very efficient.  The STREAM argument is evaluated more
  72.     than once.  Return value is -1 for EOF or error.
  73.  
  74. void Lstream_ungetc (Lstream *stream, int c)
  75.     Push one byte back onto the input queue.  This will be
  76.     the next byte read from the stream.  Any number of
  77.     bytes can be pushed back and will be read in the order
  78.     they were pushed back.  This is a macro and so it is very
  79.     efficient.  The C argument is only evaluated once but the
  80.     STREAM argument is evaluated more than once.
  81.  
  82. int Lstream_fputc (Lstream *stream, int c)
  83. int Lstream_fgetc (Lstream *stream)
  84. void Lstream_fungetc (Lstream *stream, int c)
  85.     Function equivalents of the above macros. 
  86.  
  87. int Lstream_read (Lstream *stream, void *data, int size)
  88.     Read SIZE bytes of DATA from the stream.  Return the number of
  89.     bytes read.  0 means EOF. -1 means an error occurred and no
  90.     bytes were read.
  91.  
  92. int Lstream_write (Lstream *stream, void *data, int size)
  93.     Write SIZE bytes of DATA to the stream.  Return the number of
  94.     bytes written.  -1 means an error occurred and no bytes were
  95.     written.
  96.  
  97. void Lstream_unread (Lstream *stream, void *data, int size)
  98.     Push back SIZE bytes of DATA onto the input queue.  The
  99.     bytes will be read back in the order they were pushed.  There
  100.     is no limit on the number of bytes that can be pushed back.
  101.  
  102. int Lstream_close (Lstream *stream)
  103.     Close the stream.  All data will be flushed out.
  104.  
  105. void
  106. Lstream_reopen (Lstream *stream)
  107.     Reopen a closed stream.  This enables I/O on it again.
  108.  
  109. */   
  110.  
  111. static Lisp_Object mark_lstream (Lisp_Object, void (*) (Lisp_Object));
  112. static void print_lstream (Lisp_Object obj, Lisp_Object printcharfun,
  113.                int escapeflag);
  114. static void finalize_lstream (void *header, int for_disksave);
  115. static unsigned int sizeof_lstream (CONST void *header);
  116. DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION ("stream", lstream,
  117.                     mark_lstream, print_lstream,
  118.                     finalize_lstream, 0, 0,
  119.                     sizeof_lstream, Lstream);
  120. Lisp_Object Qstreamp;
  121.  
  122. #define DEFAULT_BLOCK_BUFFERING_SIZE 512
  123. #define MAX_READ_SIZE 512
  124.  
  125. static Lisp_Object
  126. mark_lstream (Lisp_Object obj, void (*markobj) (Lisp_Object))
  127. {
  128.   Lstream *lstr = XLSTREAM (obj);
  129.   if (lstr->imp->marker)
  130.     return (lstr->imp->marker) (obj, markobj);
  131.   else
  132.     return Qnil;
  133. }
  134.  
  135. static void
  136. print_lstream (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
  137. {
  138.   Lstream *lstr = XLSTREAM (obj);
  139.   char buf[200];
  140.  
  141.   if (print_readably)
  142.     error ("printing unreadable object #<%s stream 0x%x>",
  143.        lstr->imp->name, lstr->header.uid);
  144.  
  145.   sprintf (buf, "#<%s stream 0x%x>", lstr->imp->name, lstr->header.uid);
  146.   write_c_string (buf, printcharfun);
  147. }
  148.  
  149. static void
  150. finalize_lstream (void *header, int for_disksave)
  151. {
  152.   /* WARNING WARNING WARNING.  This function (and all finalize functions)
  153.      may get called more than once on the same object, and may get called
  154.      (at dump time) on objects that are not being released. */
  155.   Lstream *lstr = (Lstream *) header;
  156.   if (lstr->is_open)
  157.     Lstream_close (lstr);
  158.   /* We set the pointers to 0 so that we don't lose when this function
  159.      is called more than once on the same object */
  160.   if (lstr->out_buffer)
  161.     {
  162.       xfree (lstr->out_buffer);
  163.       lstr->out_buffer = 0;
  164.     }
  165.   if (lstr->in_buffer)
  166.     {
  167.       xfree (lstr->in_buffer);
  168.       lstr->in_buffer = 0;
  169.     }
  170.   if (lstr->unget_buffer)
  171.     {
  172.       xfree (lstr->unget_buffer);
  173.       lstr->unget_buffer = 0;
  174.     }
  175. }
  176.  
  177. static unsigned int
  178. sizeof_lstream (CONST void *header)
  179. {
  180.   CONST Lstream *lstr = (CONST Lstream *) header;
  181.   return sizeof (*lstr) + lstr->imp->size - 1;
  182. }
  183.  
  184. void
  185. Lstream_set_buffering (Lstream *lstr, Lstream_buffering buffering,
  186.                int buffering_size)
  187. {
  188.   lstr->buffering = buffering;
  189.   switch (buffering)
  190.     {
  191.     case LSTREAM_UNBUFFERED:
  192.       lstr->buffering_size = 0; break;
  193.     case LSTREAM_BLOCK_BUFFERED:
  194.       lstr->buffering_size = DEFAULT_BLOCK_BUFFERING_SIZE; break;
  195.     case LSTREAM_BLOCKN_BUFFERED:
  196.       lstr->buffering_size = buffering_size; break;
  197.     case LSTREAM_LINE_BUFFERED:
  198.     case LSTREAM_UNLIMITED:
  199.       lstr->buffering_size = INT_MAX; break;
  200.     }
  201. }
  202.  
  203. Lstream *
  204. Lstream_new (CONST Lstream_implementation *imp)
  205. {
  206.   Lstream *p = alloc_lcrecord (sizeof (*p) + imp->size - 1,
  207.                    lrecord_lstream);
  208.   /* Zero it out, except the header. */
  209.   memset ((char *) p + sizeof (p->header), 0,
  210.       sizeof (*p) - sizeof (p->header) + imp->size - 1);
  211.   p->imp = imp;
  212.   Lstream_set_buffering (p, LSTREAM_BLOCK_BUFFERED, 0);
  213.   p->is_open = 1;
  214.   return p;
  215. }
  216.  
  217. void
  218. Lstream_reopen (Lstream *lstr)
  219. {
  220.   if (lstr->is_open)
  221.     {
  222.       Lisp_Object obj = Qnil;
  223.       XSETLSTREAM (obj, lstr);
  224.       signal_simple_error ("Internal error: lstream already open", obj);
  225.     }
  226.   lstr->is_open = 1;
  227. }
  228.  
  229. int
  230. Lstream_flush_out (Lstream *lstr)
  231. {
  232.   int num_written;
  233.  
  234.   while (lstr->out_buffer_ind > 0)
  235.     {
  236.       if (!lstr->is_open)
  237.     {
  238.       Lisp_Object obj = Qnil;
  239.       XSETLSTREAM (obj, lstr);
  240.       signal_simple_error ("Internal error: lstream not open", obj);
  241.     }
  242.       if (!lstr->imp->writer)
  243.     {
  244.       Lisp_Object obj = Qnil;
  245.       XSETLSTREAM (obj, lstr);
  246.       signal_simple_error ("Internal error: lstream has no writer", obj);
  247.     }
  248.       num_written =
  249.     (lstr->imp->writer) (lstr, lstr->out_buffer, lstr->out_buffer_ind);
  250.       if (num_written == 0 || num_written >= lstr->out_buffer_ind)
  251.     lstr->out_buffer_ind = 0;
  252.       else if (num_written >= 0)
  253.     {
  254.       memmove (lstr->out_buffer, lstr->out_buffer + num_written,
  255.            lstr->out_buffer_ind - num_written);
  256.       lstr->out_buffer_ind -= num_written;
  257.     }
  258.       if (num_written <= 0)
  259.     /* #### should we discard the data on an error? */
  260.     return -1;
  261.     }
  262.  
  263.   return 0;
  264. }
  265.  
  266. int
  267. Lstream_flush (Lstream *lstr)
  268. {
  269.   if (Lstream_flush_out (lstr) < 0)
  270.     return -1;
  271.  
  272.   /* clear out buffered data */
  273.   lstr->in_buffer_current = lstr->in_buffer_ind = 0;
  274.   lstr->unget_buffer_start = lstr->unget_buffer_end = 0;
  275.  
  276.   return 0;
  277. }
  278.  
  279. /* We want to add NUM characters.  This function ensures that the
  280.    buffer is large enough for this (per the buffering size specified
  281.    in the stream) and returns the number of characters we can
  282.    actually write. */
  283.  
  284. static int
  285. Lstream_adding (Lstream *lstr, int num)
  286. {
  287.   int size_needed = min (lstr->buffering_size,
  288.              max (lstr->out_buffer_size,
  289.                   num + lstr->out_buffer_ind));
  290.   DO_REALLOC (lstr->out_buffer, lstr->out_buffer_size,
  291.           size_needed, unsigned char);
  292.   return min (num, size_needed - lstr->out_buffer_ind);
  293. }
  294.  
  295. /* Like Lstream_write(), but does not handle line-buffering correctly. */
  296.  
  297. static int
  298. Lstream_write_1 (Lstream *stream, CONST void *data, int size)
  299. {
  300.   unsigned char *p = (unsigned char *) data;
  301.   int off = 0;
  302.   if (!stream->is_open)
  303.     {
  304.       Lisp_Object obj = Qnil;
  305.       XSETLSTREAM (obj, stream);
  306.       signal_simple_error ("Internal error: lstream not open", obj);
  307.     }
  308.   while (1)
  309.     {
  310.       /* Figure out how much we can add to the buffer */
  311.       int chunk = Lstream_adding (stream, size);
  312.       /* Do it. */
  313.       if (chunk > 0)
  314.     memcpy (stream->out_buffer + stream->out_buffer_ind, p + off, chunk);
  315.       stream->out_buffer_ind += chunk;
  316.       stream->byte_count += chunk;
  317.       size -= chunk;
  318.       off += chunk;
  319.       /* If the buffer is full and we have more to add, flush it out. */
  320.       if (size > 0)
  321.     {
  322.       if (Lstream_flush_out (stream) < 0)
  323.         {
  324.           if (off == 0)
  325.         return -1;
  326.           else
  327.         return off;
  328.         }
  329.     }
  330.       else
  331.     break;
  332.     }
  333.   return off;
  334. }
  335.  
  336. /* If the stream is not line-buffered, then we can just call
  337.    Lstream_write_1(), which writes in chunks.  Otherwise, we
  338.    repeatedly call Lstream_putc(), which knows how to handle
  339.    line buffering. */
  340.  
  341. int
  342. Lstream_write (Lstream *stream, CONST void *data, int size)
  343. {
  344.   int i;
  345.   unsigned char *p = (unsigned char *) data;
  346.  
  347.   assert (size >= 0);
  348.   if (size == 0)
  349.     return size;
  350.   if (stream->buffering != LSTREAM_LINE_BUFFERED)
  351.     return Lstream_write_1 (stream, data, size);
  352.   for (i = 0; i < size; i++)
  353.     {
  354.       if (Lstream_putc (stream, p[i]) < 0)
  355.     break;
  356.     }
  357.   return i == 0 ? -1 : 0;
  358. }
  359.  
  360. /* Assuming the buffer is empty, fill it up again. */
  361.  
  362. static int
  363. Lstream_read_more (Lstream *lstr)
  364. {
  365. #if 0
  366.   int size_needed = max (1, min (MAX_READ_SIZE, lstr->buffering_size));
  367. #else
  368.   /* If someone requested a larger buffer size, so be it! */
  369.   int size_needed = max (1, lstr->buffering_size);
  370. #endif
  371.   int size_gotten;
  372.  
  373.   if (!lstr->is_open)
  374.     {
  375.       Lisp_Object obj = Qnil;
  376.       XSETLSTREAM (obj, lstr);
  377.       signal_simple_error ("Internal error: lstream not open", obj);
  378.     }
  379.   if (!lstr->imp->reader)
  380.     {
  381.       Lisp_Object obj = Qnil;
  382.       XSETLSTREAM (obj, lstr);
  383.       signal_simple_error ("Internal error: lstream has no reader", obj);
  384.     }
  385.   DO_REALLOC (lstr->in_buffer, lstr->in_buffer_size,
  386.           size_needed, unsigned char);
  387.   size_gotten = (lstr->imp->reader) (lstr, lstr->in_buffer,
  388.                      size_needed);
  389.   lstr->in_buffer_current = max (0, size_gotten);
  390.   lstr->in_buffer_ind = 0;
  391.   return size_gotten < 0 ? -1 : size_gotten;
  392. }  
  393.  
  394. int
  395. Lstream_read (Lstream *stream, void *data, int size)
  396. {
  397.   unsigned char *p = (unsigned char *) data;
  398.   int off = 0;
  399.   int chunk;
  400.   int error_occurred = 0;
  401.  
  402.   assert (size >= 0);
  403.   if (size == 0)
  404.     return 0;
  405.  
  406.   /* First try to get some data from the unget buffer */
  407.   chunk = min (size, stream->unget_buffer_end - stream->unget_buffer_start);
  408.   if (chunk > 0)
  409.     {
  410.       memcpy (p, &stream->unget_buffer[stream->unget_buffer_start], chunk);
  411.       stream->unget_buffer_start += chunk;
  412.       stream->byte_count += chunk;
  413.       off = chunk;
  414.       size -= chunk;
  415.     }
  416.  
  417.   while (size > 0)
  418.     {
  419.       /* Take whatever we can from the in buffer */
  420.       chunk = min (size, stream->in_buffer_current - stream->in_buffer_ind);
  421.       if (chunk > 0)
  422.     memcpy (p + off, stream->in_buffer + stream->in_buffer_ind, chunk);
  423.       stream->in_buffer_ind += chunk;
  424.       stream->byte_count += chunk;
  425.       size -= chunk;
  426.       off += chunk;
  427.  
  428.       /* If we need some more, try to get some more from the stream's end */
  429.       if (size > 0)
  430.     {
  431.       int retval = Lstream_read_more (stream);
  432.       if (retval < 0)
  433.         error_occurred = 1;
  434.       if (retval <= 0)
  435.         break;
  436.     }
  437.     }
  438.  
  439.   return ((off == 0 && error_occurred) ? -1 : off);
  440. }
  441.  
  442. void
  443. Lstream_unread (Lstream *stream, void *data, int size)
  444. {
  445.   /* Move any existing unget characters to the beginning of the buffer */
  446.   if (stream->unget_buffer_start != stream->unget_buffer_end)
  447.     memmove (stream->unget_buffer,
  448.          stream->unget_buffer + stream->unget_buffer_start,
  449.          stream->unget_buffer_end - stream->unget_buffer_start);
  450.   stream->unget_buffer_end -= stream->unget_buffer_start;
  451.   stream->unget_buffer_start = 0;
  452.  
  453.   /* Make sure buffer is big enough */
  454.  
  455.   DO_REALLOC (stream->unget_buffer, stream->unget_buffer_size,
  456.           stream->unget_buffer_end + size, unsigned char);
  457.  
  458.   memcpy (stream->unget_buffer + stream->unget_buffer_end, data, size);
  459.   stream->unget_buffer_end += size;
  460.   stream->byte_count -= size;
  461. }
  462.  
  463. int
  464. Lstream_rewind (Lstream *stream)
  465. {
  466.   if (!stream->imp->rewinder)
  467.     {
  468.       Lisp_Object obj = Qnil;
  469.       XSETLSTREAM (obj, stream);
  470.       signal_simple_error ("Internal error: lstream has no rewinder", obj);
  471.     }
  472.   if (Lstream_flush (stream) < 0)
  473.     return -1;
  474.   stream->byte_count = 0;
  475.   return (stream->imp->rewinder) (stream);
  476. }
  477.   
  478. int
  479. Lstream_close (Lstream *stream)
  480. {
  481.   if (stream->is_open)
  482.     {
  483.       if (Lstream_flush (stream) < 0)
  484.     return -1;
  485.       if (stream->imp->closer)
  486.     {
  487.       if ((stream->imp->closer) (stream) < 0)
  488.         return -1;
  489.     }
  490.     }
  491.  
  492.   stream->is_open = 0;
  493.   stream->byte_count = 0;
  494.   /* Note that Lstream_flush() reset all the buffer indices.  That way,
  495.      the next call to Lstream_putc(), Lstream_getc(), or Lstream_ungetc()
  496.      on a closed stream will call into the function equivalents, which will
  497.      cause an error. */
  498.   return 0;
  499. }
  500.  
  501. int
  502. Lstream_fputc (Lstream *stream, int c)
  503. {
  504.   unsigned char ch = (unsigned char) c;
  505.   int retval = Lstream_write_1 (stream, &ch, 1);
  506.   if (retval >= 0 && stream->buffering == LSTREAM_LINE_BUFFERED && ch == '\n')
  507.     return Lstream_flush_out (stream);
  508.   return retval < 0 ? -1 : 0;
  509. }
  510.  
  511. int
  512. Lstream_fgetc (Lstream *stream)
  513. {
  514.   unsigned char ch;
  515.   if (Lstream_read (stream, &ch, 1) <= 0)
  516.     return -1;
  517.   return ch;
  518. }
  519.  
  520. void
  521. Lstream_fungetc (Lstream *stream, int c)
  522. {
  523.   unsigned char ch = (unsigned char) c;
  524.   Lstream_unread (stream, &ch, 1);
  525. }
  526.  
  527. DEFUN ("streamp", Fstreamp, Sstreamp, 1, 1, 0,
  528.        "Return non-nil if OBJECT is a stream.")
  529.   (object)
  530.   Lisp_Object object;
  531. {
  532.   return (LSTREAMP (object) ? Qt : Qnil);
  533. }
  534.  
  535.  
  536. /************************ some stream implementations *********************/
  537.  
  538. /*********** a stdio stream ***********/
  539.  
  540. struct stdio_stream
  541. {
  542.   FILE *file;
  543.   int closing;
  544. };
  545.  
  546. #define get_stdio_stream(stream) \
  547.   ((struct stdio_stream *) Lstream_data (stream))
  548.  
  549. static int stdio_reader (Lstream *stream, unsigned char *data, int size);
  550. static int stdio_writer (Lstream *stream, CONST unsigned char *data, int size);
  551. static int stdio_rewinder (Lstream *stream);
  552. static int stdio_closer (Lstream *stream);
  553.  
  554. DEFINE_LSTREAM_IMPLEMENTATION ("stdio", lstream_stdio, stdio_reader,
  555.                    stdio_writer, stdio_rewinder, stdio_closer,
  556.                    0, sizeof (struct stdio_stream));
  557.  
  558. Lisp_Object
  559. make_stdio_stream (FILE *stream, int flags)
  560. {
  561.   Lisp_Object obj = Qnil;
  562.   Lstream *lstr = Lstream_new (lstream_stdio);
  563.   struct stdio_stream *str = get_stdio_stream (lstr);
  564.   str->file = stream;
  565.   str->closing = flags & LSTR_CLOSING;
  566.   XSETLSTREAM (obj, lstr);
  567.   return obj;
  568. }
  569.  
  570. static int
  571. stdio_reader (Lstream *stream, unsigned char *data, int size)
  572. {
  573.   struct stdio_stream *str = get_stdio_stream (stream);
  574.   size_t val = fread (data, 1, (size_t) size, str->file);
  575.   if (!val && ferror (str->file))
  576.     return -1;
  577.   return (int) val;
  578. }
  579.  
  580. static int
  581. stdio_writer (Lstream *stream, CONST unsigned char *data, int size)
  582. {
  583.   struct stdio_stream *str = get_stdio_stream (stream);
  584.   size_t val = fwrite (data, 1, (size_t) size, str->file);
  585.   if (!val && ferror (str->file))
  586.     return -1;
  587.   return (int) val;
  588. }
  589.  
  590. static int
  591. stdio_closer (Lstream *stream)
  592. {
  593.   struct stdio_stream *str = get_stdio_stream (stream);
  594.   if (str->closing)
  595.     return fclose (str->file);
  596.   else
  597.     return fflush (str->file);
  598. }
  599.  
  600. static int
  601. stdio_rewinder (Lstream *stream)
  602. {
  603.   rewind (get_stdio_stream (stream)->file);
  604.   return 0;
  605. }
  606.  
  607. /*********** a file descriptor ***********/
  608.  
  609. struct filedesc_stream
  610. {
  611.   int fd;
  612.   int pty_max_bytes;
  613.   Bufbyte eof_char;
  614.   int closing:1;
  615.   int allow_quit:1;
  616. };
  617.  
  618. #define get_filedesc_stream(stream) \
  619.   ((struct filedesc_stream *) Lstream_data (stream))
  620.  
  621. static int filedesc_reader (Lstream *stream, unsigned char *data, int size);
  622. static int filedesc_writer (Lstream *stream, CONST unsigned char *data,
  623.                 int size);
  624. static int filedesc_rewinder (Lstream *stream);
  625. static int filedesc_closer (Lstream *stream);
  626.  
  627. DEFINE_LSTREAM_IMPLEMENTATION ("filedesc", lstream_filedesc, filedesc_reader,
  628.                    filedesc_writer, filedesc_rewinder,
  629.                    filedesc_closer, 0,
  630.                    sizeof (struct filedesc_stream));
  631.  
  632. Lisp_Object
  633. make_filedesc_stream (int filedesc, int flags)
  634. {
  635.   Lisp_Object obj = Qnil;
  636.   Lstream *lstr = Lstream_new (lstream_filedesc);
  637.   struct filedesc_stream *fstr = get_filedesc_stream (lstr);
  638.   fstr->fd = filedesc;
  639.   fstr->closing = !!(flags & LSTR_CLOSING);
  640.   fstr->allow_quit = !!(flags & LSTR_ALLOW_QUIT);
  641.   XSETLSTREAM (obj, lstr);
  642.   return obj;
  643. }
  644.  
  645. static int
  646. filedesc_reader (Lstream *stream, unsigned char *data, int size)
  647. {
  648.   struct filedesc_stream *str = get_filedesc_stream (stream);
  649.   return (str->allow_quit ? read_allowing_quit : read)
  650.     (str->fd, data, size);
  651. }
  652.  
  653. static int
  654. filedesc_writer (Lstream *stream, CONST unsigned char *data, int size)
  655. {
  656.   /* !!#### needs to handle PTY eof output */
  657.   struct filedesc_stream *str = get_filedesc_stream (stream);
  658.   return (str->allow_quit ? write_allowing_quit : write)
  659.     (str->fd, data, size);
  660. }
  661.  
  662. static int
  663. filedesc_rewinder (Lstream *stream)
  664. {
  665.   if (lseek (get_filedesc_stream (stream)->fd, 0, SEEK_SET) == -1)
  666.     return -1;
  667.   else
  668.     return 0;
  669. }
  670.  
  671. static int
  672. filedesc_closer (Lstream *stream)
  673. {
  674.   struct filedesc_stream *str = get_filedesc_stream (stream);
  675.   if (str->closing)
  676.     return close (str->fd);
  677.   else
  678.     return 0;
  679. }
  680.  
  681. void
  682. filedesc_stream_set_pty_flushing (Lstream *stream, int pty_max_bytes,
  683.                   Bufbyte eof_char)
  684. {
  685.   struct filedesc_stream *str = get_filedesc_stream (stream);
  686.   str->pty_max_bytes = pty_max_bytes;
  687.   str->eof_char = eof_char;
  688. }
  689.  
  690. /*********** read from a Lisp string ***********/
  691.  
  692. #define get_lisp_string_stream(stream) \
  693.   ((struct lisp_string_stream *) Lstream_data (stream))
  694.  
  695. struct lisp_string_stream
  696. {
  697.   Lisp_Object obj;
  698.   Bytecount offset, end;
  699. };
  700.  
  701. static int lisp_string_reader (Lstream *stream, unsigned char *data, int size);
  702. static int lisp_string_rewinder (Lstream *stream);
  703. static Lisp_Object lisp_string_marker (Lisp_Object stream,
  704.                        void (*markobj) (Lisp_Object));
  705.  
  706. DEFINE_LSTREAM_IMPLEMENTATION ("lisp-string", lstream_lisp_string,
  707.                    lisp_string_reader, 0, lisp_string_rewinder,
  708.                    0, lisp_string_marker,
  709.                    sizeof (struct lisp_string_stream));
  710.  
  711. Lisp_Object
  712. make_lisp_string_stream (Lisp_Object string, Bytecount offset,
  713.              Bytecount len)
  714. {
  715.   Lisp_Object obj = Qnil;
  716.   Lstream *lstr;
  717.   struct lisp_string_stream *str;
  718.  
  719.   CHECK_STRING (string, 0);
  720.   if (len < 0)
  721.     len = string_length (XSTRING (string)) - offset;
  722.   assert (offset >= 0);
  723.   assert (len >= 0);
  724.   assert (offset + len <= string_length (XSTRING (string)));
  725.  
  726.   lstr = Lstream_new (lstream_lisp_string);
  727.   str = get_lisp_string_stream (lstr);
  728.   str->offset = offset;
  729.   str->end = offset + len;
  730.   str->obj = string;
  731.   XSETLSTREAM (obj, lstr);
  732.   return obj;
  733. }
  734.                   
  735. static int
  736. lisp_string_reader (Lstream *stream, unsigned char *data, int size)
  737. {
  738.   struct lisp_string_stream *str = get_lisp_string_stream (stream);
  739.   /* Don't lose if the string shrank past us ... */
  740.   Bytecount offset = min (str->offset, string_length (XSTRING (str->obj)));
  741.   Bufbyte *strstart = string_data (XSTRING (str->obj));
  742.   Bufbyte *start = strstart + offset;
  743.  
  744.   /* ... or if someone changed the string and we ended up in the
  745.      middle of a character. */
  746.   VALIDATE_CHARPTR_BACKWARD (start);
  747.   offset = start - strstart;
  748.   size = min (size, str->end - offset);
  749.   assert (size >= 0); /* paranoia */
  750.   memcpy (data, start, size);
  751.   str->offset = offset + size;
  752.   return size;
  753. }
  754.  
  755. static int
  756. lisp_string_rewinder (Lstream *stream)
  757. {
  758.   get_lisp_string_stream (stream)->offset = 0;
  759.   return 0;
  760. }
  761.  
  762. static Lisp_Object
  763. lisp_string_marker (Lisp_Object stream, void (*markobj) (Lisp_Object))
  764. {
  765.   struct lisp_string_stream *str = get_lisp_string_stream (XLSTREAM (stream));
  766.   return str->obj;
  767. }
  768.  
  769. /*********** a fixed buffer ***********/
  770.  
  771. #define get_fixed_buffer_stream(stream) \
  772.   ((struct fixed_buffer_stream *) Lstream_data (stream))
  773.  
  774. struct fixed_buffer_stream
  775. {
  776.   unsigned char *buf;
  777.   int size;
  778.   int offset;
  779. };
  780.  
  781. static int fixed_buffer_reader (Lstream *stream, unsigned char *data,
  782.                 int size);
  783. static int fixed_buffer_writer (Lstream *stream, CONST unsigned char *data,
  784.                 int size);
  785. static int fixed_buffer_rewinder (Lstream *stream);
  786.  
  787. DEFINE_LSTREAM_IMPLEMENTATION ("fixed-buffer", lstream_fixed_buffer,
  788.                    fixed_buffer_reader, fixed_buffer_writer,
  789.                    fixed_buffer_rewinder,
  790.                    0, 0,
  791.                    sizeof (struct fixed_buffer_stream));
  792.  
  793. Lisp_Object
  794. make_fixed_buffer_stream (unsigned char *buf, int size)
  795. {
  796.   Lisp_Object obj = Qnil;
  797.   Lstream *lstr;
  798.   struct fixed_buffer_stream *str;
  799.  
  800.   lstr = Lstream_new (lstream_fixed_buffer);
  801.   str = get_fixed_buffer_stream (lstr);
  802.   str->buf = buf;
  803.   str->size = size;
  804.   XSETLSTREAM (obj, lstr);
  805.   return obj;
  806. }
  807.                   
  808. static int
  809. fixed_buffer_reader (Lstream *stream, unsigned char *data, int size)
  810. {
  811.   struct fixed_buffer_stream *str = get_fixed_buffer_stream (stream);
  812.   size = min (size, str->size - str->offset);
  813.   memcpy (data, str->buf + str->offset, size);
  814.   str->offset += size;
  815.   return size;
  816. }
  817.  
  818. static int
  819. fixed_buffer_writer (Lstream *stream, CONST unsigned char *data, int size)
  820. {
  821.   struct fixed_buffer_stream *str = get_fixed_buffer_stream (stream);
  822.   if (str->offset == str->size)
  823.     {
  824.       /* If we're at the end, just throw away the data and pretend
  825.      we wrote all of it.  If we return 0, then the lstream routines
  826.      will try again and again to write it out. */
  827.       return size;
  828.     }
  829.   size = min (size, str->size - str->offset);
  830.   memcpy (str->buf + str->offset, data, size);
  831.   str->offset += size;
  832.   return size;
  833. }
  834.  
  835. static int
  836. fixed_buffer_rewinder (Lstream *stream)
  837. {
  838.   get_fixed_buffer_stream (stream)->offset = 0;
  839.   return 0;
  840. }
  841.  
  842. unsigned char *
  843. fixed_buffer_stream_ptr (Lstream *stream)
  844. {
  845.   assert (stream->imp == lstream_fixed_buffer);
  846.   return get_fixed_buffer_stream (stream)->buf;
  847. }
  848.  
  849. /*********** write to a resizing buffer ***********/
  850.  
  851. #define get_resizing_buffer_stream(stream) \
  852.   ((struct resizing_buffer_stream *) Lstream_data (stream))
  853.  
  854. struct resizing_buffer_stream
  855. {
  856.   unsigned char *buf;
  857.   int allocked;
  858.   int stored;
  859. };
  860.  
  861. static int resizing_buffer_writer (Lstream *stream, CONST unsigned char *data,
  862.                    int size);
  863. static int resizing_buffer_rewinder (Lstream *stream);
  864. static int resizing_buffer_closer (Lstream *stream);
  865.  
  866. DEFINE_LSTREAM_IMPLEMENTATION ("resizing-buffer", lstream_resizing_buffer,
  867.                    0, resizing_buffer_writer,
  868.                    resizing_buffer_rewinder,
  869.                    resizing_buffer_closer, 0,
  870.                    sizeof (struct resizing_buffer_stream));
  871.  
  872. Lisp_Object
  873. make_resizing_buffer_stream (void)
  874. {
  875.   Lisp_Object obj = Qnil;
  876.   XSETLSTREAM (obj, Lstream_new (lstream_resizing_buffer));
  877.   return obj;
  878. }
  879.                   
  880. static int
  881. resizing_buffer_writer (Lstream *stream, CONST unsigned char *data, int size)
  882. {
  883.   struct resizing_buffer_stream *str = get_resizing_buffer_stream (stream);
  884.   DO_REALLOC (str->buf, str->allocked, str->stored + size, unsigned char);
  885.   memcpy (str->buf + str->stored, data, size);
  886.   str->stored += size;
  887.   return size;
  888. }
  889.  
  890. static int
  891. resizing_buffer_rewinder (Lstream *stream)
  892. {
  893.   get_resizing_buffer_stream (stream)->stored = 0;
  894.   return 0;
  895. }
  896.  
  897. static int
  898. resizing_buffer_closer (Lstream *stream)
  899. {
  900.   struct resizing_buffer_stream *str = get_resizing_buffer_stream (stream);
  901.   if (str->buf)
  902.     {
  903.       xfree (str->buf);
  904.       str->buf = 0;
  905.     }
  906.   return 0;
  907. }
  908.  
  909. unsigned char *
  910. resizing_buffer_stream_ptr (Lstream *stream)
  911. {
  912.   assert (stream->imp == lstream_resizing_buffer);
  913.   return get_resizing_buffer_stream (stream)->buf;
  914. }
  915.  
  916. /************ read from a Lisp buffer ************/
  917.  
  918. #define get_lisp_buffer_stream(stream) \
  919.   ((struct lisp_buffer_stream *) Lstream_data (stream))
  920.  
  921. struct lisp_buffer_stream
  922. {
  923.   struct buffer *buf;
  924.   Bufpos start, end;
  925.   int flags;
  926. };
  927.  
  928. static int lisp_buffer_reader (Lstream *stream, unsigned char *data,
  929.                    int size);
  930. static Lisp_Object lisp_buffer_marker (Lisp_Object stream,
  931.                        void (*markobj) (Lisp_Object));
  932.  
  933. DEFINE_LSTREAM_IMPLEMENTATION ("lisp-buffer", lstream_lisp_buffer,
  934.                    lisp_buffer_reader, 0,
  935.                    0, 0, lisp_buffer_marker,
  936.                    sizeof (struct lisp_buffer_stream));
  937.  
  938. Lisp_Object
  939. make_lisp_buffer_stream (struct buffer *buf, Bufpos start, Bufpos end,
  940.              int flags)
  941. {
  942.   Lisp_Object obj = Qnil;
  943.   Lstream *lstr;
  944.   struct lisp_buffer_stream *str;
  945.   Bufpos bmin, bmax;
  946.  
  947.   if (flags & LSTR_IGNORE_ACCESSIBLE)
  948.     {
  949.       bmin = BUF_BEG (buf);
  950.       bmax = BUF_Z (buf);
  951.     }
  952.   else
  953.     {
  954.       bmin = BUF_BEGV (buf);
  955.       bmax = BUF_ZV (buf);
  956.     }
  957.  
  958.   if (start == -1)
  959.     start = bmin;
  960.   if (end == -1)
  961.     end = bmax;
  962.   assert (bmin <= start);
  963.   assert (start <= bmax);
  964.   assert (bmin <= end);
  965.   assert (end <= bmax);
  966.   assert (start <= end);
  967.  
  968.   lstr = Lstream_new (lstream_lisp_buffer);
  969.   str = get_lisp_buffer_stream (lstr);
  970.   str->buf = buf;
  971.   str->start = start;
  972.   str->end = end;
  973.   str->flags = flags;
  974.   XSETLSTREAM (obj, lstr);
  975.   return obj;
  976. }
  977.  
  978. static int
  979. lisp_buffer_reader (Lstream *stream, unsigned char *data, int size)
  980. {
  981.   struct lisp_buffer_stream *str = get_lisp_buffer_stream (stream);
  982.   Bytind bimin, bimax;
  983.   unsigned char *orig_data = data;
  984.   Bytind start;
  985.   Bytind end;
  986.  
  987.  
  988.   /* It's safer to keep START and END in the stream structure in
  989.      Bufpos's in case the buffer's text changes, but we need to
  990.      do all our operations in Bytind's.  Keep in mind that SIZE
  991.      is a value in bytes, not chars. */
  992.   if (str->flags & LSTR_IGNORE_ACCESSIBLE)
  993.     {
  994.       bimin = BI_BUF_BEG (str->buf);
  995.       bimax = BI_BUF_Z (str->buf);
  996.     }
  997.   else
  998.     {
  999.       bimin = BI_BUF_BEGV (str->buf);
  1000.       bimax = BI_BUF_ZV (str->buf);
  1001.     }
  1002.   start = bytind_clip_to_bounds (bimin,
  1003.                  bufpos_to_bytind (str->buf, str->start),
  1004.                  bimax);
  1005.   end = bytind_clip_to_bounds (bimin,
  1006.                    bufpos_to_bytind (str->buf, str->end),
  1007.                    bimax);
  1008.   
  1009.   size = min (size, end - start);
  1010.   end = start + size;
  1011.   VALIDATE_BYTIND_BACKWARD (str->buf, end);
  1012.  
  1013.   while (start < end)
  1014.     {
  1015.       Bytind ceil;
  1016.       Bytecount chunk;
  1017.  
  1018.       if (str->flags & LSTR_IGNORE_ACCESSIBLE)
  1019.     ceil = BI_BUF_CEILING_OF_IGNORE_ACCESSIBLE (str->buf, start);
  1020.       else
  1021.     ceil = BI_BUF_CEILING_OF (str->buf, start);
  1022.       chunk = min (ceil, end) - start;
  1023.       memcpy (data, BI_BUF_BYTE_ADDRESS (str->buf, start), chunk);
  1024.       data += chunk;
  1025.       start += chunk;
  1026.     }
  1027.  
  1028.   str->start = bytind_to_bufpos (str->buf, end);
  1029.  
  1030.   if (EQ (str->buf->selective_display, Qt) && str->flags & LSTR_SELECTIVE)
  1031.     {
  1032.       /* What a kludge.  What a kludge.  What a kludge. */
  1033.       unsigned char *p;
  1034.       for (p = orig_data; p < data; p++)
  1035.     if (*p == '\r')
  1036.       *p = '\n';
  1037.     }
  1038.  
  1039.   return data - orig_data;
  1040. }
  1041.  
  1042. static Lisp_Object
  1043. lisp_buffer_marker (Lisp_Object stream, void (*markobj) (Lisp_Object))
  1044. {
  1045.   struct lisp_buffer_stream *str =
  1046.     get_lisp_buffer_stream (XLSTREAM (stream));
  1047.   Lisp_Object buffer = Qnil;
  1048.  
  1049.   XSETBUFFER (buffer, str->buf);
  1050.   return buffer;
  1051. }
  1052.  
  1053.  
  1054. /************************************************************************/
  1055. /*                            initialization                            */
  1056. /************************************************************************/
  1057.  
  1058. void
  1059. syms_of_lstream (void)
  1060. {
  1061.   defsymbol (&Qstreamp, "streamp");
  1062.   defsubr (&Sstreamp);
  1063. }
  1064.